/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Model;

import java.io.Serializable;
import java.util.Timer;
import java.util.TimerTask;

/**
 *Crossing contains the complete model
 * with lane's, car's and lights
 * each drawn dynamically
 * @author Pro
 * 
 */
public class Crossing implements Serializable{

    private int hLanes, vLanes;
    private int timerCount = 1;
    private int delayCount = 1;
    private Lane[] lanes;
    private Timer timerMove = new Timer();
    private Timer timerBing = new Timer();
    private boolean paused = true;



    /**
     *Constructor of this class with two Integer values
     * @param hLs is the number of horizontal lanes
     * @param vLs is the number of horizontal lanes
     */
    public Crossing(int hLs, int vLs) {

        hLanes = hLs;
        vLanes = vLs;
        lanes = new Lane[(hLs + vLs)];

        for (int i = 0; i < lanes.length; ++i) {

            lanes[i] = new Lane(i, hLs, vLs);
        }

        for (int i = 0; i < lanes.length; ++i) {
            lanes[i].setLanes(lanes);
        }

        TimerTask moveTask = new TimerTask() {

            @Override
            public void run() {

                if (!paused) {
                    moveCars();
                }
            }
        };

        TimerTask bingTask = new TimerTask() {

            @Override
            public void run() {

                if (!paused) {
                    newCars();
                }
            }
        };

        TimerTask lightsTask = new TimerTask() {

            @Override
            public void run() {

                if (!paused) {

   if ((timerCount % 400) == 0) {

                        if (lanes[0].getLights().getGreen()) {

                            delayCount = (vLanes * 80);
                        } else {

                            delayCount = (hLanes * 80);
                        }

                        for (int i = 0; i < lanes.length; i++) {

                            if (lanes[i].getLights().getGreen()) {

                                lanes[i].getLights().setAmberDelay(true);
                            }
                        }
                    }

                    if ((timerCount % 450) == 0) {

                        for (int i = 0; i < lanes.length; i++) {

                            if (lanes[i].getLights().getAmberDelay()) {

                                lanes[i].getLights().setAmberDelay(false);
                                lanes[i].getLights().setGreen(false);
                            } else {

                                lanes[i].getLights().setRedWait(true);
                            }
                        }
                    }


                    if (timerCount == (450 + delayCount)) {

                        for (int i = 0; i < lanes.length; i++) {

                            if (lanes[i].getLights().getRedWait()) {

                                lanes[i].getLights().setGreen(true);
                                lanes[i].getLights().setRedWait(false);
                            }
                        }

                        timerCount = 0;
                    }

                    //System.out.println("COUNTING     " + timerCount);
                    timerCount++;
                }
            }
        };

        timerMove.schedule(moveTask, 500, 50);
        timerBing.schedule(bingTask, 500, 500);
        timerMove.schedule(lightsTask, 500, 20);

    }

    /**
     *Public method that reference to lanes object
     * @return value of type Lane[]
     */
    public synchronized Lane[] getLanes() {
        return lanes;
    }

    /**
     *Public method that  changes hLanes to desired amount
     * @param hLanes is Integer type
     */
    public void sethLanes(int hLanes) {
        this.hLanes = hLanes;
    }

    /**
     *Public method that  changes vLanes to desired amount
     * @param vLanes is Integer type
     */
    public void setvLanes(int vLanes) {
        this.vLanes = vLanes;
    }

    /**
     *Public method that passes value from Lane[] to main
     * @param i is a known value for the horizontal or vertical
     * @return sends the value of i
     */
    public int getFlows(int i) {

        int x = lanes[i].getFlow();
        return x;
    }

    /**
     *Public method that  returns timers current operational status
     * @return value of type boolean
     */
    public boolean isPaused() {
        return paused;
    }

    /**
     *Public method is a boolean "on/off" switch for timers
     * @param paused is of type boolean
     */
    public synchronized void setPaused(boolean paused) {
        this.paused = paused;
    }

    /**
     *Public method that sets value of probability for distinct Lane objects
     * @param flow i is a known value for the horizontal or vertical
     * @param carProb is new value of car generation
     */
    public void setCarProb(int flow, int carProb) {

        for (int i = 0; i < lanes.length; i++) {

            if (lanes[i].getFlow() == flow) {
                lanes[i].setCarProb(carProb);
            }
        }
    }

    /**
     * Public method that new cars
     * 
     */
    public synchronized void newCars() {

        for (int i = 0; i < lanes.length; i++) {

            lanes[i].bingCar();
        }
    }

    /**
     * Public method that Move cars
     *
     */
    public synchronized void moveCars() {


        for (int i = 0; i < lanes.length; i++) {

            lanes[i].moveCars();

        }
    }
}
